Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Use hash of reactive value object to determine if it has changed #1428

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

gadenbuie
Copy link
Collaborator

@gadenbuie gadenbuie commented May 27, 2024

Starting a PR to help the discussion we've had around reactive.value objects and mutability.

Before - Reactivity with mutable objects

The key problem can be seen in the example from Reactivity | Mutable objects. In this example, currently, even if you call .set() on a reactive object, if the object was mutated in place .set() doesn't invalidate reactivity because the new value and the current value are already the same.

from shiny import reactive
from shiny.express import input, render, ui

ui.input_numeric("x", "Enter a value to add to the list:", 1)
ui.input_action_button("submit", "Add Value")


@render.code
def out():
    return f"Values: {user_provided_values()}"


# Stores all the values the user has submitted so far
user_provided_values = reactive.value([])


@reactive.effect
@reactive.event(input.submit)
def add_value_to_list():
    # WATCHOUT! This doesn't work as expected!
    values = user_provided_values()
    values.append(input.x())
    user_provided_values.set(values)

Kapture 2024-05-27 at 14 55 03

The best approach for updating the reactive value is to create a new instance of the reactive value, e.g.

@reactive.effect
@reactive.event(input.submit)
def add_value_to_list():
    values = user_provided_values()
    user_provided_values.set([*values, input.x()])

This works well for lists -- once you become aware of the problem, of course -- and dictionaries, but is easy to run into with other mutable objects that might be harder to copy.

After -- Compare new (mutable object) values by hash

This PR uses xxHash to hash mutable objects to then compare the new value with the hash of the old value when .set() was last called. After this change the example above works as most people would expect.

Kapture 2024-05-27 at 14 55 50

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant